package com.itheima.youdianda.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.youdianda.common.R;
import com.itheima.youdianda.domain.*;
import com.itheima.youdianda.dto.*;
import com.itheima.youdianda.exception.CustomException;
import com.itheima.youdianda.service.*;
import com.itheima.youdianda.dto.ChageNamePro;
import com.itheima.youdianda.showBuDing.service.MyYddArticleService;
import com.itheima.youdianda.utils.GetIP;
import com.itheima.youdianda.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName UserController
 * @Description 用户登录控制器
 * @Author Young
 * @Date 2023/2/11 14:07
 * @Version 1.0
 */
@Slf4j
@RestController
@RequestMapping("/index")
public class IndexController {

    @Value("${YouDianDa.salt}")
    private String salt;//读取固定的盐值
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysConfigService sysconfigService;
    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysDictService sysDictService;
    @Autowired
    private YddCateService yddCateService;
    @Autowired
    private YddArticleService yddArticleService;
    @Autowired
    private YddAdvposService yddAdvposService;
    @Autowired
    private YddTagService yddTagService;
    @Autowired
    private YddAdvimgService yddAdvimgService;
    @Autowired
    private YddUserService yddUserService;
    @Autowired
    private YddLinkService yddLinkService;
    @Autowired
    private MyYddArticleService  myYddArticleService;


    /**
     * 后台系统登录
     * @param map
     * @return
     */
    @PostMapping("/login")
    public R<Map> login(HttpServletRequest request, @RequestBody Map map){
        log.info("接收到用户登录的请求: {}",map);
        //获取登录信息
        String loginName = (String) map.get("login_name");
        String password = (String) map.get("password");
        //处理发送过来的密码
        String md5Password = DigestUtils.md5DigestAsHex((password + salt).getBytes());
        //查询用户是否存在
        LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
        query.eq(SysUser::getLoginName,loginName);
        SysUser user = sysUserService.getOne(query);
        //账号密码校验
        if (user != null){
            //账号存在. 但密码错误
            if (!md5Password.equals(user.getPassword())) {
                return R.error("密码有误,请检查并重新输入 ==>>");
            }
            //判断用户状态
            if (user.getStatus() == 0) {
                return R.error("用户已被禁用");
            }
            //正常用户,正确登录修改最后登陆时间,和登录ip
            user.setLoginDate(LocalDateTime.now());
            user.setLoginIp(GetIP.getIP(request));
            sysUserService.updateById(user);

            //重构用户信息 ======>>> 准备返回
            map.put("userId", user.getId());
            //对上面 最终产物 进行token
            return R.success(JwtUtils.giveToken(map));
        }else{};
            //账号不存在
            return R.error("账号不存在,请联系管理员 ==>>");
    }

    /**
     * 获取系统配置
     * @return
     */
    @GetMapping("/getConfig")
    public R<Map> systemConfig() {
        LambdaQueryWrapper<SysConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysConfig::getTabValue, "system");
        List<SysConfig> sysConfigs = sysconfigService.list(wrapper);

        HashMap<String, String> map = new HashMap<>();
        for (SysConfig sysConfig : sysConfigs) {
            map.put(sysConfig.getAttrKey(), sysConfig.getAttrValue());
        }

        return R.success(map);

    }

    /**
     * 用户、菜单、字典, 等配置信息查询
     * @param request
     * @return
     */
    @PostMapping("/profile")
    public R<Map> profile(HttpServletRequest request) {
        //获取前端的token
        String token = request.getHeader("x-token");
        //解析拿到Claims
        Claims claims = JwtUtils.getClaims(token);
        //{login_name=admin, password=111111, exp=1676194138}
        String loginName = (String) claims.get("login_name");
        //开始查询数据库,并封装
        //查询user表
        LambdaQueryWrapper<SysUser> SysUserWrapper = new LambdaQueryWrapper<>();
        SysUserWrapper.eq(SysUser::getLoginName,loginName);
        SysUser user = sysUserService.getOne(SysUserWrapper);
        //------------------------------------------------------------------------
        String roleIdStr = user.getRoleId();
        String[] roleIds = roleIdStr.split(",");

        List<String> sysRoleList = new ArrayList<>();

        for (String id : roleIds) {
            SysRole sysRole = sysRoleService.getById(id);
            sysRoleList.add(sysRole.getName());
        }

        //以上两表合并 返回==> userInfo
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(user,userInfo);
        userInfo.setRoleName(sysRoleList);
        //----------------------------------------------------------------------------
        List<String> roleMenuIdList = new ArrayList();

        for (String roleId : roleIds) {
            LambdaQueryWrapper<SysRoleMenu> SysRoleMenuWrapper = new LambdaQueryWrapper<>();
            SysRoleMenuWrapper.eq(SysRoleMenu::getRoleId,roleId);
            List<SysRoleMenu> list = sysRoleMenuService.list(SysRoleMenuWrapper);

            for (SysRoleMenu good : list) {
                roleMenuIdList.add(good.getMenuId());
            }

        }
        //------------------------------------------------------------------------------
//        //封装 menuList(菜单列表)
//        LambdaQueryWrapper<SysRoleMenu> SysRoleMenuWrapper = new LambdaQueryWrapper<>();
//        //根据用户角色ID, 查询出对应的菜单ID对应的数据, 分装成集合
//        SysRoleMenuWrapper.eq(SysRoleMenu::getRoleId,userInfo.getRoleId());
//        List<SysRoleMenu> list = sysRoleMenuService.list(SysRoleMenuWrapper);
//        List idList =list.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
//        //根据菜单ID, 查询出菜单对象, 放到集合中==>>返回出去
////        List<SysMenu> sysMenus = sysMenuService.listByIds(idList);
        LambdaQueryWrapper<SysMenu> sysMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysMenuLambdaQueryWrapper.eq(SysMenu::getType, 1);
        sysMenuLambdaQueryWrapper.eq(SysMenu::getIsShow, 1);
//        sysMenuLambdaQueryWrapper.in(SysMenu::getId, idList);
        sysMenuLambdaQueryWrapper.in(SysMenu::getId, roleMenuIdList);
        List<SysMenu> sysMenus = sysMenuService.list(sysMenuLambdaQueryWrapper);


        //封装dictsList (数据字典)
        //先给dicts分组
        LambdaQueryWrapper<SysDict> sysDictWrapper = new LambdaQueryWrapper<>();
        sysDictWrapper.select(SysDict::getType).groupBy(SysDict::getType);
        //按类型分组, 获取到所有的类型
        List<Object> dictTypes = sysDictService.listObjs(sysDictWrapper);
        //准备容器
        Map<String, Map<String,String>> newList = new HashMap<>();
        //操作每种类型
        for (Object type : dictTypes) {
            Map<String, String> map = new HashMap<>();
            sysDictWrapper = new LambdaQueryWrapper<>();
            //根据类型(type)查询出, 对应的一条记录, 封装成对象
            sysDictWrapper.eq(SysDict::getType,type);
            List<SysDict> dicts = sysDictService.list(sysDictWrapper);
            //遍历拿到的对象, 进行装配
            for (SysDict sysDict : dicts) {
                //拿到Value  对应的Labe
                map.put(sysDict.getValue(),sysDict.getLabel());
            }

            // 最后封装 返回==>>type : {"0": "单表","1": "主表"}, 访问外层大map
            newList.put((String)type,map);
        }

        //btnList
        Map btnList = new HashMap<>();
        btnList.put("btnList","*");

        //打包数据 == 发送
        Map map = new HashMap();
        map.put("userInfo",userInfo);
        map.put("menuList",sysMenus);
        map.put("dictsList",newList);
        map.put("btnList",btnList);

        return R.success(map);
    }

    /**
     * 主页统计信息
     * @param request
     * @return
     */
    @GetMapping("/baseInfo")
    public R<Map> baseInfo(HttpServletRequest request){
        //获取前端的token
        String token = request.getHeader("x-token");
        //解析拿到Claims        {login_name=admin, password=111111, exp=1676222884}
        Claims claims = JwtUtils.getClaims(token);
        //查询 分类数据 拿到每种分类的各个对象
        List<YddCate> yddCateList = yddCateService.list();
        //遍历处理yddCateList
        List<YddCate> cates = yddCateList.stream().map(item -> {
            //获取每种分类对象的id
            Integer cateId = item.getId();
            LambdaQueryWrapper<YddArticle> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(YddArticle::getCateid, cateId);
            int count = yddArticleService.count(queryWrapper);
            item.setSortNum(count);
            return item;
        }).collect(Collectors.toList());
        HashMap<String,Object> map = new HashMap<>();
        map.put("all_cate",cates);
        //分类总数
        Integer cateCount = yddCateService.count();
        map.put("cate_num",cateCount);
        //广告图备注
        Integer advimgCount = yddAdvimgService.count();
        map.put("advimg_num",advimgCount);
        //广告位总数
        Integer count = yddAdvposService.count();
        map.put("advpos_num",count);
        //标签的总数
        Integer tagCount = yddTagService.count();
        map.put("tag_num",tagCount);
        //管理员数量
        Integer userCount = sysUserService.count();
        map.put("admin_num",userCount);
        //文章总数
        Integer articleCount = yddArticleService.count();
        map.put("article_num",articleCount);


        LambdaQueryWrapper<YddUser> yddUserQuery = new LambdaQueryWrapper<>();
        yddUserQuery.orderByDesc(YddUser::getId).last("limit 7");
        List<YddUser> yddUserList = yddUserService.list(yddUserQuery);
        map.put("new_user",yddUserList);

        LambdaQueryWrapper<YddArticle> yddArticleQuery = new LambdaQueryWrapper<>();
        yddArticleQuery.orderByDesc(YddArticle::getLovenum).last("limit 7");
        List<YddArticle> yddArticles = yddArticleService.list(yddArticleQuery);
        map.put("hot_article",yddArticles);

        Map<String,Integer> userMap = new HashMap();
        int totalCount = yddUserService.count();
        yddUserQuery = new LambdaQueryWrapper<>();
        yddUserQuery.eq(YddUser::getSex,0);  //男的数量
        int user_man = yddUserService.count(yddUserQuery);
        int user_women = totalCount - user_man;
        userMap.put("total",totalCount);
        userMap.put("user_man",user_man);
        userMap.put("user_woman",user_women);
        map.put("user",userMap);

        return R.success(map);
    }

    /**
     * 热门置顶文章数据(首页)
     * @param pageStr
     * @param limitStr
     * @return
     */
    @GetMapping("/new")
    public R<Map> myNew(@RequestParam("page") String pageStr,  @RequestParam("limit")String limitStr){
        //把前端传来的page、和limit
        int page = Integer.parseInt(pageStr);
        int limit = Integer.parseInt(limitStr);
        //创建容器,存放所有需要的数据
        Map<String, Object> resultMap = new HashMap();

        //ArticleDto articleDto = new ArticleDto();
        //yddArticleDto articleDtoChild = new yddArticleDto();

        //设置首页大列表
        resultMap.put("desc","首页大列表");

        //24小时最新文章数量
        LambdaQueryWrapper<YddArticle> dayQueryWrapper = new LambdaQueryWrapper<>();
        dayQueryWrapper.ge(YddArticle::getCreateDate,System.currentTimeMillis() - 24*60*60*1000);
        int dayNumber = yddArticleService.count(dayQueryWrapper);
        resultMap.put("num_day",dayNumber);
        //articleDto.setNum_day(dayNumber);

        //一周文章最新数量
        LambdaQueryWrapper<YddArticle> weekQueryWrapper = new LambdaQueryWrapper<>();
        weekQueryWrapper.ge(YddArticle::getCreateDate,System.currentTimeMillis() - 7*24*60*60*1000);
        int weekNumber = yddArticleService.count(weekQueryWrapper);
        resultMap.put("num_week",weekNumber);
        //articleDto.setNum_week(weekNumber);

        //页面细节数据(list)
        Map<String, Object> listMap = new HashMap();
        //总页数
        //Page<YddArticle> pageInfo = new Page<>(page, limit);//分页构造器
        //LambdaQueryWrapper<YddArticle> listQueryWrapper = new LambdaQueryWrapper<>();//筛选是否 删除、置顶、推荐
        //listQueryWrapper.eq(YddArticle::getStatus,2).eq(YddArticle::getIshot, 1).eq(YddArticle::getIstop, 1);
        ChageNamePro chageNamePro = artList(page, limit);

        //总数
        //articleDto.setCount(yddArticleService.count(listQueryWrapper));
        //yddArticleService.page(pageInfo,listQueryWrapper);

        resultMap.put("list",chageNamePro);

        return R.success(resultMap);
    }


    /**
     * 最新文章
     * @return
     */
    @GetMapping("/hot")
    public R<Map> hot() {
        //创建容器,存放所有需要的数据
        Map<String, Object> resultMap = new HashMap();
        LambdaQueryWrapper<YddArticle> queryWrapper = new LambdaQueryWrapper<>();
        //条件过滤
        queryWrapper.orderByDesc(YddArticle::getCreateDate).eq(YddArticle::getStatus,2)
                .eq(YddArticle::getIshot,1).eq(YddArticle::getIstop,1).last("limit 10");
        List<YddArticle> articleList = yddArticleService.list(queryWrapper);
        //开始封装数据
        List<HotDto> hotDtos = articleList.stream().map(item -> {
            HotDto hotDto = new HotDto();
            BeanUtils.copyProperties(item, hotDto);
            //根据分类id查询分类名
            Integer cateid = item.getCateid();
            YddCate cate = yddCateService.getById(cateid);
            if (cate != null) hotDto.setCatename(cate.getCatename());
            return hotDto;
        }).collect(Collectors.toList());

        //===>返送给前端
        resultMap.put("desc", "最新文章");
        resultMap.put("list", hotDtos);
        return R.success(resultMap);
    }

    /**
     * 文章详情数据
     * @param id
     * @return
     */
    @GetMapping("/show")
    public R show(Integer id) { // 等待service接入
        //Map map = yddArticleService.show(id);
        //return R.success(map);
        Map map = myYddArticleService.show(id);
        return R.success(map);
    }

    /**
     * 用户注册
     * @param yddUser
     * @return
     */
    @PostMapping("/reg")
    public R<Map> reg(@RequestBody YddUser yddUser) {
        //获取注册用户的手机号和密码
        String mobile = yddUser.getMobile();
        String password = yddUser.getPassword();
        //根据手机号查询用户的数据
        LambdaQueryWrapper<YddUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(YddUser::getMobile, mobile);
        YddUser user = yddUserService.getOne(lqw);
        //查看用户是否存在
        if (user != null) throw new CustomException("当前手机号已经注册~  ");
        //若不存在, 进行自动注册, 保持入库
        password = DigestUtils.md5DigestAsHex((password + salt).getBytes());
        yddUser.setPassword(password);
        yddUser.setUsername(mobile);
        yddUser.setNotes("此人很懒,并没有描述 ~");
        yddUser.setSex(0);
        yddUserService.save(yddUser);

        //====>>> 组装返回
        //创建容器,存放所有需要的数据
        Map<String, Object> resultMap = new HashMap();
        Map<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("id", yddUser.getId());
        tokenMap.put("mobile", yddUser.getMobile());

        resultMap.put("token", JwtUtils.giveToken(tokenMap));

        return R.success(resultMap);
    }

    /**
     * 文章列表数据
     * @param page
     * @param limit
     * @param cateid
     * @return
     */
    @GetMapping("/list")
    public R<Map> list(Integer page, Integer limit, Integer cateid) {

        HashMap<String,Object> hashMap = new HashMap<>();
        PageDto<YddArticle> yddArticlePageDto = this.artList(page, limit, cateid);
        hashMap.put("list",yddArticlePageDto);

        return R.success(hashMap);
    }

    /**
     * 推荐文章
     * @return
     */
    @GetMapping("/recommend")
    public R<Map> recommend() {
        //创建容器,存放所有需要的数据
        Map<String, Object> resultMap = new HashMap();
        LambdaQueryWrapper<YddArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(YddArticle::getCreateDate).eq(YddArticle::getIshot, 1)
                .eq(YddArticle::getStatus,2).eq(YddArticle::getIstop,1).last("limit 10");
        List<YddArticle> articleList = yddArticleService.list(queryWrapper);

        //拼接封装数据
        List<RecommendDto> recommendDtoList = articleList.stream().map(item -> {
            RecommendDto recommendDto = new RecommendDto();
            BeanUtils.copyProperties(item, recommendDto);

            //根据分类id查询分类名
            Integer cateid = item.getCateid();
            YddCate cate = yddCateService.getById(cateid);
            if (cate != null) recommendDto.setCatename(cate.getCatename());

            return recommendDto;
        }).collect(Collectors.toList());
        //===>>
        resultMap.put("desc", "推荐文章");
        resultMap.put("list", recommendDtoList);
        return R.success(resultMap);
    }

    /**
     * 首页和全局数据
     * @return
     */
    @GetMapping("/index")
    public R index(){
        //创建容器,存放所有需要的数据
        Map<String, Object> resultMapPro = new HashMap();
        Map<String, Object> resultMap = new HashMap();

        //查询所有分类
        List<YddCate> list = yddCateService.list();
        resultMap.put("allCate",list);

        //data
        List<SysConfig> configs = sysconfigService.list();
        Map<String, Object> cofigMap = new HashMap<>();
        cofigMap.put("data",configs);





//        resultMap.put("config")

        //所有友情链接  (allTag)
        List<YddTag> tagList = yddTagService.list();
        resultMap.put("allTag",tagList);
        //所有友情链接(allLink)
        List<YddLink> linkList = yddLinkService.list();
        resultMap.put("allLink",linkList);
        //轮播图数据
        List<YddAdvimg> advimgList = yddAdvimgService.list();
        resultMap.put("banner",advimgList);
        //侧边栏图片
        List<YddAdvimg> sideBanner = yddAdvimgService.list();
        resultMap.put("sideBanner",sideBanner);
        //详情广告图
        List<YddAdvimg> showBanner = yddAdvimgService.list();
        resultMap.put("showBanner",showBanner);



        resultMapPro.put("data",resultMap);
        return R.success(resultMap);
    }



    /**
     *
     * @param page
     * @param limit
     * @Author 小竹
     * @return
     */
    public ChageNamePro artList(Integer page, Integer limit) {

        Page<YddArticle> pageInfo = new Page<>(page,limit);
        Page<YddArticleDto> dtoPageInfo = new Page<>();
        //根据条件查询
        LambdaQueryWrapper<YddArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(YddArticle::getStatus,2).eq(YddArticle::getIshot, 1).eq(YddArticle::getIstop, 1);

        yddArticleService.page(pageInfo,queryWrapper);
        //将内容copy给dto
        BeanUtils.copyProperties(pageInfo,dtoPageInfo,"records");
        //封装dtoPageInfo中的数据

        ChageNamePro chageNameProc = new ChageNamePro();

        List<YddArticle> records = pageInfo.getRecords();
        List<YddArticleDto> dtoList=records.stream().map((item)->{
            YddArticleDto yddArticleDto = new YddArticleDto();
            BeanUtils.copyProperties(item,yddArticleDto);
            YddCate yddCate = yddCateService.getById(item.getCateid());
            String catename = yddCate.getCatename();
            yddArticleDto.setCatename(catename);
            return yddArticleDto;
        }).collect(Collectors.toList());
        dtoPageInfo.setRecords(dtoList);
        //return dtoPageInfo;
        chageNameProc.setCount(dtoPageInfo.getTotal());//Count
        chageNameProc.setTotalPages(dtoPageInfo.getPages());//TotalPages
        chageNameProc.setPageSize(dtoPageInfo.getSize());//PageSize
        chageNameProc.setCurrentPage(dtoPageInfo.getCurrent());//CurrentPage
        chageNameProc.setData(dtoList);

        return chageNameProc;

    }

    public PageDto<YddArticle> artList(Integer page,  Integer limit, Integer cateid) {
        Page<YddArticle> pageInfo = new Page<>(page,limit);
        //根据条件查询
        LambdaQueryWrapper<YddArticle> queryWrapper = new LambdaQueryWrapper<>();
        //条件
        queryWrapper.eq(YddArticle::getCateid, cateid);
        queryWrapper.eq(YddArticle::getStatus,2);
        yddArticleService.page(pageInfo,queryWrapper);
        PageDto<YddArticle> pageDto = new PageDto<YddArticle>();
        BeanUtils.copyProperties(pageInfo,pageDto,"records");
        pageDto.setValue(pageInfo);
        return pageDto;
    }

}
